package analiseSintatica.Regras.Funcao;

import java.util.LinkedList;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.*;
import analiseSintatica.estruturadados.NoArvore;
import analiseSintatica.Regras.Tipos.RegraTipoPrimitivo;

public class RegraArgsDeclaracao extends Regra{


    //<args_declaracao> ::= (<tipo_primitivo> | identificador) ["*"] identificador {"," (<tipo_primitivo> | identificador) ["*"] identificador } 

    protected static Regra instancia;
    protected String estrutura = "(<tipo_primitivo> | identificador) ['*'] identificador {',' (<tipo_primitivo> | identificador) ['*'] identificador }";


    /**
     * Construtor privado necessario ao singleton
     */
    private RegraArgsDeclaracao() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     *
     *
     */
    public static RegraArgsDeclaracao getInstance() {
        if (instancia == null) {
            instancia = new RegraArgsDeclaracao();
        }
        return (RegraArgsDeclaracao) instancia;
    }
    

    @Override
    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
        
        ErroSintaticoException erros = new ErroSintaticoException();
        
        NoArvore NaoTerminalArgsDeclaracao = new NoArvore("<args_declaracao>", false);

        try{
            if(RegraTipoPrimitivo.getInstance().getPrimeiro().contains(listaTokens.getFirst().getLexema())){
                NaoTerminalArgsDeclaracao.adicionaFilho(RegraTipoPrimitivo.getInstance().analisar(listaTokens));
            }else{
                NaoTerminalArgsDeclaracao.adicionaFilho(reconheceToken(listaTokens, "identificador",estrutura));
            }
        }catch(ErroSintaticoException e){
            
        }

        if(listaTokens.getFirst().getLexema().equals("*")){
           NaoTerminalArgsDeclaracao.adicionaFilho(reconheceLexema(listaTokens, "operador_multiplicacao", "*",estrutura));

        }
        
        try{
            NaoTerminalArgsDeclaracao.adicionaFilho(reconheceToken(listaTokens, "identificador",estrutura));

        }catch(ErroSintaticoException e){

        }

        try{
            while(listaTokens.getFirst().getLexema().equals(",")){
                try{
                        if(RegraTipoPrimitivo.getInstance().getPrimeiro().contains(listaTokens.getFirst().getLexema())){
                            NaoTerminalArgsDeclaracao.adicionaFilho(RegraTipoPrimitivo.getInstance().analisar(listaTokens));
                    }else{
                         NaoTerminalArgsDeclaracao.adicionaFilho(reconheceToken(listaTokens, "identificador",estrutura));
                    }

                }catch(ErroSintaticoException e){

                }

                if(listaTokens.getFirst().getLexema().equals("*")){
                    NaoTerminalArgsDeclaracao.adicionaFilho(reconheceLexema(listaTokens, "operador_multiplicacao", "*",estrutura));

                }

                try{
                    NaoTerminalArgsDeclaracao.adicionaFilho(reconheceToken(listaTokens, "identificador",estrutura));

                }catch(ErroSintaticoException e){

                }
                
          }

        }catch(ErroSintaticoException e){
            
        }
        

        return NaoTerminalArgsDeclaracao;
    }


    @Override
    protected void setPrimeiro() {
        this.primeiro.add("identificador");
        this.primeiro.add("char");
        this.primeiro.add("int");
        this.primeiro.add("float");
        this.primeiro.add("boolean");
        
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    protected void setSeguinte() {
        this.seguinte.add(")");

        //throw new UnsupportedOperationException("Not supported yet.");
    }


}
